package org.example.array;

import java.util.Arrays;
import java.util.Iterator;
import java.util.function.Consumer;
import java.util.stream.IntStream;

/**
 * @author wujiale
 * 使用迭代器需要实现 Iterable接口
 */
public class DynamicArray implements Iterable<Integer>{


    //存储数组中元素的个数 逻辑大小
    private int size = 0;

    //存储数组的容量
    private int capacity = 8;

    // 存储数组 初始状态 创建出来后元素初始值都是 0
    //private int[] array = new int[capacity];
    //创建时先创建空数组 真正用到时再去添加
    private int[] array = {};

    public void addLast(int element){
        array[size] = element;
        size++;
    }

    public void add(int index,int element){
        //检查扩容
        checkAndGrow();
        // 可以等于size 就是插入到末尾
        if(index < 0 || index > size){
            throw new RuntimeException("index out of bound");
        }
        // 第一个参数是源数组 第二个是起始位置 第三个是目标数组 第四个是目标数组的起始位置 第五个是复制的长度
        // 将index开始的元素向后移动1位
        if(size != index){
            System.arraycopy(array,index,array,index+1,size-index);
        }
        array[index] = element;
        size++;
    }

    private void checkAndGrow() {
        if(size==0){
            array = new int[capacity];
        }
        if(size == capacity){
            //扩容
            capacity += capacity >> 1;
            //扩容
            int[] newArray = new int[capacity];
            //将旧数组中的元素复制到新数组中
            System.arraycopy(array,0,newArray,0,size);
            array = newArray;
        }
    }

    public int get(int index){
        // [0,size)
        if(index < 0 || index >= size){
            throw new RuntimeException("index out of bound");
        }
        return array[index];
    }


    /**
     * 传入一个元素 没有返回值 consumer最合适
     * 接受一个Consumer类型的函数式接口作为参数
     * 该函数的作用是将数组中的每个元素一次传递给该函数式接口所表示的消费型函数进行处理
     * 有且仅有一个accept方法
     * @param consumer 处理函数
     */
    public void foreach(/*函数式接口*/Consumer<Integer> consumer){
        for (int i = 0; i < size; i++) {
            //System.out.println(array[i]);
            //提供元素
            consumer.accept(array[i]);
            //传入的函数没有返回值
        }
    }

    /**
     * Iterable是一个接口，返回Iterator需要先有一个实现类
     * 迭代器
     * @return Iterator
     */
    @Override
    public Iterator<Integer> iterator() {
        // 匿名内部类
        return new Iterator<Integer>() {
            int i = 0;
            /**
             * 有无下一个元素
             * @return Boolean
             */
            @Override
            public boolean hasNext() {
                return i < size;
            }

            /**
             * 返回当前元素 指针指向下一个元素
             * @return Integer
             */
            @Override
            public Integer next() {
                return array[i++];
            }
        };
    }

    /**
     * 获取流
     * @return stream
     */
    public IntStream stream(){
        //这里不能直接传入整个array 因为array包含了无效部分
        //Arrays.copyOfRange    不包含尾部索引
        return IntStream.of(Arrays.copyOfRange(array,0,size));
    }

    public Integer remove(int index){
        if(index<0 || index>=size){
            throw new ArrayIndexOutOfBoundsException();
        }
        int result = array[index];
        if(index != size-1){
            System.arraycopy(array,index+1,array,index,size-index-1);
        }
        size--;
        return result;
    };

    public static void main(String[] args) {
        DynamicArray dynamicArray = new DynamicArray();
        dynamicArray.addLast(1);
        dynamicArray.addLast(2);
        dynamicArray.addLast(3);
        dynamicArray.addLast(4);
        dynamicArray.addLast(5);

        dynamicArray.forEach(System.out::println);

        dynamicArray.add(2,6);

        for (Integer element : dynamicArray) {
            //增强for循环就是每次获取元素时都去掉用 hasNext()方法
            //再调用next()方法 把当前元素赋值给一个变量
            //增强for是语法糖 底层还是迭代器
            System.out.println(element);
        }

        System.out.println("stream--------------");
        dynamicArray.stream().forEach(System.out::println);

        dynamicArray.remove(2);
        System.out.println("remove2--------------");
        dynamicArray.stream().forEach(System.out::println);

        dynamicArray.remove(4);
        System.out.println("remove4--------------");
        dynamicArray.stream().forEach(System.out::println);
    }



}
